#pragma once
#include <iostream>
#include <string>
#include <list>
#include <memory>
#include <algorithm>
#include <sys/types.h>
#include <sys/socket.h>

#include "Initadd.h"
#include "Log.h"
#include "Mutex.h"

using namespace LogMudule;
using namespace lxp;

class UserInterface
{

public:
    virtual ~UserInterface() = default;
    virtual void Sendto(int socker, const std::string &message) = 0;
    virtual bool operator==(const IntAddr &u) = 0;
    virtual std::string Id() = 0;
};
class User : public UserInterface
{
public:
    User(const IntAddr &id) : _id(id)
    {
    }
    void Sendto(int socker, const std::string &message)
    {
        LOG(LogLevel::INFO) << "send message to" << _id.Addr() << "info" << message;
        int n = ::sendto(socker, message.c_str(), sizeof(message), 0, _id.NetAddr(), _id.Netaddrlen());
        if (n < 0)
        {
            LOG(LogLevel::ERROR) << "sendto error";
        }
    }
    bool operator==(const IntAddr &u) override
    {
        return _id == u;
    }
    std::string Id() override
    {
        return _id.Addr();
    }
    ~User()
    {
    }

private:
    IntAddr _id;
};

class UserManager
{
public:
    UserManager()
    {
    }
    void Adduser(IntAddr &id)
    {
        LockGuard lockguard(_mutex);
        for (auto &user : _online_user)
        {
            if (*user == id)
            {
                LOG(LogLevel::ERROR) << id.Addr() << "已存在用户添加失败";
                return;
            }
        }
        LOG(LogLevel::INFO) << "新增用户" << id.Addr();
        _online_user.push_back(std::make_shared<User>(id));
    }
    void DelUser(IntAddr &addr)
    {
        auto pos = std::remove_if(_online_user.begin(), _online_user.end(), [&addr](std::shared_ptr<UserInterface> &user)
                                  { return *user == addr; });
        _online_user.erase(pos, _online_user.end());
    }
    void Router(int sockfd, const std::string &message)
    {
        LockGuard lockguard(_mutex);
        for (auto &user : _online_user)
        {
            user->Sendto(sockfd, message);
        }
    }
    ~UserManager() {};

private:
    std::list<std::shared_ptr<UserInterface>> _online_user;
    Mutex _mutex;
};